LayerUnion
Layer
Layer<'input, 'error, 'output> builds an environment or service bundle from an input value, running inside a
Scope so acquired resources are finalized when the provided flow finishes. Read the
composing layers guide for the layer { } provisioning walkthrough.
Combinator inventory
| Function | Use |
|---|---|
Layer.succeed value |
A value that is already built |
Layer.envWith projection |
A value read from the layer's input |
Layer.fromFlow build |
Construction written as a flow: it can fail, read the input, and acquire scoped resources that live as long as the provided flow |
Layer.acquireRelease acquire release |
A resource built by another layer, released when the provided flow ends |
Layer.addFinalizer release |
Cleanup that runs when the provided flow ends |
Layer.map, Layer.mapError, Layer.widenError |
Change the output or the error type |
Layer.bind |
A step that depends on an earlier value, like let! |
Layer.zip |
Two layers in sequence |
Layer.zipPar, Layer.merge |
Two layers in parallel |
Layer.map2, Layer.map3 |
Combine outputs without nested tuples |
Composition rules
Layer.zip provisions left then right, sequentially. Layer.zipPar provisions both sides independently in parallel
and returns a tuple. Layer.merge is the layer-domain name for zipPar; prefer it when combining service bundles or
environment fragments. Layer.merge does not merge service contracts or synthesize a new environment type — it only
provisions both sides and returns their outputs, so build the final environment yourself.
Layer error types must match the flow error type. When provisioning steps use different errors, map them into one
startup error type with Layer.mapError before calling Layer.provide. A layer that cannot fail, such as
BaseRuntime.live or Clock.layer, has error type Never; Layer.widenError gives it any error type.
Parallel composition uses parent-owned child scopes, so when one parallel branch fails after another acquired
resources, the acquired resources are still released. If both parallel branches fail, Axial preserves both failures
as Cause.Both (leftCause, rightCause) rather than discarding one side.
Specification
Summary
| Name | Signature | Synopsis |
|---|---|---|
| Operations | ||
| fromFlow | Layer.fromFlow build | Creates a layer that builds its output by running a flow with the layer's input as its environment. |
| succeed | Layer.succeed value | Creates a layer that succeeds with a fixed output value. |
| envWith | Layer.envWith projection | Projects part of the input environment into the layer output. |
| addFinalizer | Layer.addFinalizer release | Registers a release flow with the layer scope. |
| acquireRelease | Layer.acquireRelease acquire release | Acquires a resource and registers its release with the layer scope. |
| pool | Layer.pool size acquire | Provisions a fixed-size pool of resource instances, handed out round-robin. |
| map | Layer.map mapper layer | Maps the successful output of a layer. |
| mapError | Layer.mapError mapper layer | Maps the typed provisioning failure of a layer. |
| widenError | Layer.widenError layer | Gives a layer that cannot fail with a typed error any error type. |
| bind | Layer.bind binder layer | Sequences layer provisioning with a dependent follow-up layer. |
| zip | Layer.zip left right | Builds two layers from the same input and scope and returns both outputs. |
| zipPar | Layer.zipPar left right | Builds two independent layers in parallel and returns both outputs. |
| merge | Layer.merge left right | Merges two independent service layers in parallel. |
| map2 | Layer.map2 mapper left right | Combines two layers with a mapping function. |
| apply | Layer.apply layer value | Applies a layer-wrapped function to a layer-wrapped value. |
| map3 | Layer.map3 mapper left middle right | Combines three layers with a mapping function. |
| provide | Layer.provide layer flow | Builds an environment with a layer, runs a downstream flow, and always closes the layer scope. |
Operations
Parameters
| Name | Type | Description |
|---|---|---|
| build | Flow<'input, 'error, 'output> | The flow that builds the layer output. |
Returns
Verification Examples
let database : Layer<AppConfig, DbError, Database> =
Layer.fromFlow (Flow.scopeAcquireRelease (Database.connect ()) Database.close)Parameters
| Name | Type | Description |
|---|---|---|
| acquire | Layer<'input, 'error, 'resource> | The layer that acquires the resource. |
| release | 'resource -> Flow<'input, Never, unit> | The release flow run, with the layer's input as its environment, when the layer scope closes. |
Returns
Parameters
| Name | Type | Description |
|---|---|---|
| size | int | The number of instances to provision. Must be at least one. |
| acquire | int -> Layer<'input, 'error, 'resource> | Builds one instance, given its zero-based index in the pool. |
Returns
Verification Examples
let checkerPool =
Layer.pool 4 (fun _ -> Layer.succeed (FSharpChecker.Create(keepAssemblyContents = true)))Parameters
| Name | Type | Description |
|---|---|---|
| layer | Layer<'input, Never, 'output> |
Returns
Verification Examples
let runtime : Layer<unit, string, int> = Layer.succeed 1 |> Layer.widenErrorParameters
| Name | Type | Description |
|---|---|---|
| mapper | 'left -> 'middle -> 'right -> 'output | |
| left | Layer<'input, 'error, 'left> | |
| middle | Layer<'input, 'error, 'middle> | |
| right | Layer<'input, 'error, 'right> |
Returns
Parameters
| Name | Type | Description |
|---|---|---|
| layer | Layer<'input, 'error, 'environment> | The layer that builds the downstream environment. |
| flow | Flow<'environment, 'error, 'value> | The flow to run with the provided environment. |
Returns
Verification Examples
let program () =
let runtimeLayer = Layer.succeed "production"
let workflow = Flow.envWith String.length
Layer.provide runtimeLayer workflow
